﻿using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using System.Collections.Generic;

namespace ADiKt {
    /// <summary>
    /// Helper for reading input from keyboard. This class 
    /// tracks both the current and previous state of the input devices, and implements 
    /// query methods for high level input actions such as "move up through the menu"
    /// or "pause the game".
    /// </summary>
    /// 
    public class InputState {
        public const int MaxInputs = 4;
        public readonly KeyboardState[] CurrentKeyboardStates;
        public readonly KeyboardState[] LastKeyboardStates;

        /// Constructs a new input state.
        public InputState() {
            CurrentKeyboardStates = new KeyboardState[MaxInputs];
            LastKeyboardStates = new KeyboardState[MaxInputs];
        }

        /// Reads the latest state of the keyboard and gamepad.
        public void Update() {
            for (int i = 0; i < MaxInputs; i++) {
                LastKeyboardStates[i] = CurrentKeyboardStates[i];
                CurrentKeyboardStates[i] = Keyboard.GetState((PlayerIndex)i);
            }
        }

        /// Helper for checking if a key was newly pressed during this update.
        public bool IsNewKeyPress(Keys key, PlayerIndex? controllingPlayer, out PlayerIndex playerIndex) {
            if (controllingPlayer.HasValue) {
                // Read input from the specified player.
                playerIndex = controllingPlayer.Value;
                int i = (int)playerIndex;
                return (CurrentKeyboardStates[i].IsKeyDown(key) && LastKeyboardStates[i].IsKeyUp(key));
            } else {
                // Accept input from any player.
                return (IsNewKeyPress(key, PlayerIndex.One, out playerIndex) ||
                        IsNewKeyPress(key, PlayerIndex.Two, out playerIndex) ||
                        IsNewKeyPress(key, PlayerIndex.Three, out playerIndex) ||
                        IsNewKeyPress(key, PlayerIndex.Four, out playerIndex));
            }
        }

        /// Checks for a "menu select" input action.
        public bool IsMenuSelect(PlayerIndex? controllingPlayer, out PlayerIndex playerIndex) {
            return IsNewKeyPress(Keys.Space, controllingPlayer, out playerIndex) || IsNewKeyPress(Keys.Enter, controllingPlayer, out playerIndex);
        }

        /// Checks for a "menu cancel" input action.
        public bool IsMenuCancel(PlayerIndex? controllingPlayer, out PlayerIndex playerIndex) {
            return IsNewKeyPress(Keys.Escape, controllingPlayer, out playerIndex);
        }

        /// Checks for a "menu up" input action.
        public bool IsMenuUp(PlayerIndex? controllingPlayer) {
            PlayerIndex playerIndex;
            return IsNewKeyPress(Keys.Up, controllingPlayer, out playerIndex);
        }

        /// Checks for a "menu down" input action.
        public bool IsMenuDown(PlayerIndex? controllingPlayer) {
            PlayerIndex playerIndex;
            return IsNewKeyPress(Keys.Down, controllingPlayer, out playerIndex);
        }

        /// Checks for a "menu left" input action.
        public bool IsMenuLast(PlayerIndex? controllingPlayer, out PlayerIndex playerIndex) {
            return IsNewKeyPress(Keys.Left, controllingPlayer, out playerIndex);
        }

        /// Checks for a "menu right" input action.
        public bool IsMenuNext(PlayerIndex? controllingPlayer, out PlayerIndex playerIndex) {
            return IsNewKeyPress(Keys.Right, controllingPlayer, out playerIndex);
        }

        /// Checks for a "pause the game" input action.
        public bool IsPauseGame(PlayerIndex? controllingPlayer) {
            PlayerIndex playerIndex;
            return IsNewKeyPress(Keys.Escape, controllingPlayer, out playerIndex);
        }
    }
}
